<?php
// +----------------------------------------------------------------------
// | INPHP
// | Copyright (c) https://inphp.cc All rights reserved.
// | 该文件源码由INPHP官方提供，使用协议以INPHP官方公告为准。
// +----------------------------------------------------------------------
// | 解压VITS模型压缩包
// +----------------------------------------------------------------------
namespace app\vits\cmd;

use Inphp\Core\Util\File;

class unzipVITSModel
{
    //压缩包目录
    private string $from = '';
    //要解压到哪个目录
    private string $to = '';

    private string $prefix = '';

    private string $gpt = '';
    private string $so = '';
    public function __construct(array $params = [])
    {
        $this->from = $params["from"] ?? '';
        $this->to = $params["to"] ?? '';
        $this->prefix = $params["prefix"] ?? '';
        $this->gpt = $params["gpt"] ?? '';
        $this->so = $params["so"] ?? '';
    }

    public function run()
    {
        if (empty($this->from) || empty($this->to)) {
            echo '未声明解压目录'.PHP_EOL;
            return;
        }
        if (!is_dir($this->from) || !is_dir($this->to)) {
            echo '目录无效'.PHP_EOL;
            return;
        }
        //读取目录
        $dir = opendir($this->from);
        if (!$dir) {
            echo '目录打开失败'.PHP_EOL;
            return;
        }
        //临时目录
        $tmp = $this->from."/tmp";
        if (!is_dir($tmp) && !mkdir($tmp, 0777)) {
            echo '无法创建临时目录'.PHP_EOL;
            return;
        }

        $rows = 0;
        while ($fileName = readdir($dir)) {
            if($fileName != "." && $fileName != ".." && stripos($fileName, ".") !== 0 && strtolower(strrchr($fileName, ".")) === ".zip") {
                $fileSrc = $this->from."/".$fileName;
                $rows++;
                echo "[正在处理] -> ".$fileName.PHP_EOL;
                //
                $zip = new \ZipArchive();
                if ($zip->open($fileSrc) !== true) {
                    echo "[读取失败] -> {$fileName}".PHP_EOL;
                    continue;
                }
                //解压到临时目录
                if (!$zip->extractTo($tmp)) {
                    echo "[解压失败] -> {$fileName}".PHP_EOL;
                    continue;
                }
                $zip->close();
                //从临时目录处理文件
                echo "[解压成功] -> {$fileName} -> {$tmp}".PHP_EOL;
                //搬文件，只取3个文件
                $name = substr($fileName, 0, -4);
                if (stripos($name, "_") > 0) {
                    //$name = explode("_", $name)[0];
                }
                $fd = $tmp."/v4";
                $files = $this->getFiles($fd, ["pth", "ckpt", "wav", "mp3"]);
                if (empty($files)) {
                    echo "[无文件匹配] -> {$fileName}".PHP_EOL;
                } else {
                    //构造文件结构
                    $toDir = $this->prefix.$name;
                    if (!is_dir($this->to."/".$toDir) && !mkdir($this->to."/".$toDir)) {
                        //删除临时文件夹
                        @File::deleteDir($fd);
                        echo "[处理失败] -> {$fileName} -> 无法创建目标文件夹".PHP_EOL;
                        continue;
                    }
                    //处理文件
                    foreach ($files as $f) {
                        $fn = substr(strrchr($f, "/"), 1);
                        //
                        $suffix = strtolower(strrchr($fn, "."));
                        $fName = substr($fn, 0, -strlen($suffix));
                        if (!is_file($this->to."/".$toDir."/".$toDir.($suffix == ".mp3" || $suffix == ".wav" ? "_audio" : "").$suffix)) {
                            //转移文件
                            if (!rename($f, $this->to."/".$toDir."/".$toDir.($suffix == ".mp3" || $suffix == ".wav" ? "_audio" : "").$suffix)) {
                                echo "[拷贝失败] -> {$fileName} -> {$fn}".PHP_EOL;
                                continue;
                            }
                            if ($suffix == ".mp3" || $suffix == ".wav") {
                                //
                                @file_put_contents($this->to."/".$toDir."/".$toDir."_txt".".txt", $fName);
                            }
                        } else {
                            //跳过文件
                            echo "[跳过文件] -> {$fileName}".PHP_EOL;
                        }
                        if ($suffix == ".pth" && !empty($this->so) && is_dir($this->so) && !is_file($this->so."/".$toDir.$suffix)) {
                            //
                            if (copy($this->to."/".$toDir."/".$toDir.$suffix, $this->so."/".$toDir.$suffix)) {
                                echo "[已拷贝至GPT] -> {$this->so}/{$toDir}{$suffix}".PHP_EOL;
                            }
                        }
                        if ($suffix == ".ckpt" && !empty($this->gpt) && is_dir($this->gpt) && !is_file($this->gpt."/".$toDir.$suffix)) {
                            //
                            if (copy($this->to."/".$toDir."/".$toDir.$suffix, $this->gpt."/".$toDir.$suffix)) {
                                echo "[已拷贝至SO] -> {$this->gpt}/{$toDir}{$suffix}".PHP_EOL;
                            }
                        }
                        if ($suffix == ".mp3" || $suffix == ".wav") {
                            //
                            @file_put_contents($this->so."/".$toDir."_txt".".txt", $fName);
                            @file_put_contents($this->gpt."/".$toDir."_txt".".txt", $fName);
                            if (!is_file($this->gpt."/".$toDir."_audio".$suffix)) {
                                @copy($this->to."/".$toDir."/".$toDir."_audio".$suffix, $this->gpt."/".$toDir."_audio".$suffix);
                            }
                            if (!is_file($this->so."/".$toDir."_audio".$suffix)) {
                                @copy($this->to."/".$toDir."/".$toDir."_audio".$suffix, $this->so."/".$toDir."_audio".$suffix);
                            }
                        }
                    }
                    echo "[处理完成] -> {$fileName}".PHP_EOL;
                }
                //删除临时文件夹
                @File::deleteDir($fd);
                //间隔200毫秒
                usleep(200);
            }
        }
        closedir($dir);
        echo "共{$rows}个文件".PHP_EOL;
    }

    public function getFiles(string $dir, array $matchSuffix = []): array
    {
        if (!is_dir($dir)) return [];
        $d = opendir($dir);
        if (!$d) return [];
        if (!empty($matchSuffix)) {
            foreach ($matchSuffix as &$suffix) {
                $suffix = strtolower(stripos($suffix, ".") === 0 ? $suffix : (".".$suffix));
            }
        }
        $files = [];
        while ($fileName = readdir($d)) {
            if($fileName != "." && $fileName != ".." && stripos($fileName, ".") !== 0) {
                if (is_dir($dir."/".$fileName)) {
                    $files = array_merge($files, $this->getFiles($dir."/".$fileName));
                } else {
                    $ext = strrchr($fileName, ".");
                    if ((!empty($matchSuffix) && in_array($ext, $matchSuffix)) || empty($matchSuffix)) {
                        $files[] = $dir."/".$fileName;
                    }
                }
            }
        }
        return $files;
    }
}